﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using AMS.Configuration.Properties;

namespace AMS.Configuration
{
    /// <summary>
    /// 
    /// </summary>
    /// <remarks>ReversedDict的实现约束字典的键和值都必需具有唯一的值</remarks>
    public class Dict
    {
        private Dict()
        {
        }

        private static Dict instance;
        /// <summary>
        /// 唯一的实例
        /// </summary>
        public static Dict Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Dict();
                    instance.LoadDictData();
                }

                return instance;
            }
        }

        Dictionary<int, Dictionary<string, string>> mainDict;
        Dictionary<int, Dictionary<string, string>> mainReversedDict;

        private void LoadDictData()
        {
            string dictPath = AmsEnvironment.GetSystemPath(SystemPath.DictFile);
            StreamReader reader = new StreamReader(dictPath, Encoding.Default, true);

            int lastKey = 0;
            mainDict = new Dictionary<int, Dictionary<string, string>>();
            Dictionary<string, string> subDict = null;
            while (true)
            {
                string line = reader.ReadLine();
                if (string.IsNullOrEmpty(line))
                {
                    break;
                }

                string[] tokens = line.Split('|');
                int key = int.Parse(tokens[0]);
                if (key == lastKey)
                {
                    subDict.Add(tokens[1], tokens[2]);
                }
                else
                {
                    if (subDict != null)
                    {
                        mainDict.Add(lastKey, subDict);
                    }

                    subDict = new Dictionary<string, string>();
                    subDict.Add(tokens[1], tokens[2]);
                    lastKey = key;
                }
            }

            if (subDict != null)
            {
                mainDict.Add(lastKey, subDict);
            }
        }

        /// <summary>
        /// 获取键对应的字典值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="subKey"></param>
        /// <returns></returns>
        public string GetDictValue(int key, string subKey)
        {
            if (mainDict.ContainsKey(key))
            {
                Dictionary<string, string> subDict = mainDict[key];
                if (subDict.ContainsKey(subKey))
                {
                    return subDict[subKey];
                }
                else
                {
                    throw new DictionaryEntryNotFoundException(string.Format("找不到{0}号字典的键{1}", key, subKey));
                }
            }
            else
            {
                throw new DictionaryEntryNotFoundException(string.Format("找不到{0}号字典", key));
            }
        }

        /// <summary>
        /// 获取键对应的字典值，并不抛出异常。如果键不在字典中，则返回null.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="subKey"></param>
        /// <returns></returns>
        public string GetDictValueWithNoException(int key, string subKey)
        {
            if (mainDict.ContainsKey(key))
            {
                Dictionary<string, string> subDict = mainDict[key];
                if (subDict.ContainsKey(subKey))
                {
                    return subDict[subKey];
                }
            }

            return null;
        }

        /// <summary>
        /// 获取字典的值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="subKey"></param>
        /// <param name="dictValue"></param>
        /// <returns></returns>
        public bool TryGetDictValue(int key, string subKey, out string dictValue)
        {
            if (mainDict.ContainsKey(key))
            {
                Dictionary<string, string> subDict = mainDict[key];
                if (subDict.ContainsKey(subKey))
                {
                    dictValue = subDict[subKey];
                    return true;
                }
            }

            dictValue = null;
            return false;
        }

        /// <summary>
        /// 获取字典值对应的键
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public string GetDictKey(int key, string value)
        {
            if (mainDict.ContainsKey(key))
            {
                InitReversedDict(key);

                Dictionary<string, string> subReversedDict = mainReversedDict[key];
                if (subReversedDict.ContainsKey(value))
                {
                    return subReversedDict[value];
                }
                else
                {
                    throw new DictionaryEntryNotFoundException(string.Format("找不到{0}号字典的值{1}对应的键", key, value));
                }
            }
            else
            {
                throw new DictionaryEntryNotFoundException(string.Format("找不到{0}号字典", key));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public IDictionary<string, string> GetAllKeyValues(int key)
        {
            if (mainDict.ContainsKey(key))
            {
                return mainDict[key];
            }

            return null;
        }

        /// <summary>
        /// 获取字典下的所有子字典，并进行排序，再组合成 key - value 的形式，以字符串数组返回
        /// </summary>
        /// <param name="key"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public string[] GetKeyValueStringList(int key, DictItemSort sort, out string[] subKeys)
        {
            return GetKeyValueStringList(key, sort, true, true, out subKeys);
        }
        /// <summary>
        /// 获取字典下的所有子字典，并进行排序，再组合成 key - value 的形式，以字符串数组返回
        /// </summary>
        /// <param name="key"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public string[] GetKeyValueStringList(int key, DictItemSort sort)
        {
            string[] subKeys;
            return GetKeyValueStringList(key, sort, true, false, out subKeys);
        }
        /// <summary>
        /// 获取字典下的所有子字典，并进行排序，再组合成 value 的形式，以字符串数组返回
        /// </summary>
        /// <param name="key"></param>
        /// <param name="sort"></param>
        /// <param name="subKeys"></param>
        /// <returns></returns>
        public string[] GetKeyValueStringListWithoutSubKey(int key, DictItemSort sort, out string[] subKeys)
        {
            return GetKeyValueStringList(key, sort, false, true, out subKeys);
        }
        /// <summary>
        /// 获取字典下的所有子字典，并进行排序，再组合成 value 的形式，以字符串数组返回
        /// </summary>
        /// <param name="key"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public string[] GetKeyValueStringListWithoutSubKey(int key, DictItemSort sort)
        {
            string[] subKeys;
            return GetKeyValueStringList(key, sort, false, false, out subKeys);
        }

        /// <summary>
        /// 获取一个key下面所有的子KEY-VALUE对，并按一定的方式排序
        /// </summary>
        /// <param name="key"></param>
        /// <param name="sort"></param>
        /// <param name="subKeyInText"></param>
        /// <param name="getSubKeys"></param>
        /// <param name="subKeys"></param>
        /// <returns></returns>
        private string[] GetKeyValueStringList(int key, DictItemSort sort, bool subKeyInText, bool getSubKeys, out string []subKeys)
        {
            if (!mainDict.ContainsKey(key))
            {
                subKeys = null;
                return null;
            }

            Dictionary<string, string> subDict;
            if (sort == DictItemSort.SortByKeyAscending || sort == DictItemSort.SortByKeyDecending)
            {
                subDict = mainDict[key];
            }
            else
            {
                InitReversedDict(key);
                subDict = mainReversedDict[key];
            }

            List<string> subKeyList = new List<string>();
            List<string> items = new List<string>(subDict.Keys);
            if (sort == DictItemSort.SortByKeyAscending || sort == DictItemSort.SortByNameAscending)
            {
                items.Sort();
            }
            else
            {
                items.Sort(new Comparison<string>(delegate(string strA, string strB)
                    {
                        return string.Compare(strB, strA);
                    }));
            }

            if (sort == DictItemSort.SortByKeyAscending || sort == DictItemSort.SortByKeyDecending)
            {
                for (int i = 0; i < items.Count; i++)
                {
                    items[i] = subKeyInText ? string.Format("{0} - {1}", items[i], subDict[items[i]]) : subDict[items[i]];
                    if (getSubKeys)
                    {
                        subKeyList.Add(items[i]);
                    }
                }
            }
            else
            {
                for (int i = 0; i < items.Count; i++)
                {
                    items[i] = subKeyInText ? string.Format("{0} - {1}", subDict[items[i]], items[i]) : items[i];
                    if (getSubKeys)
                    {
                        subKeyList.Add(subDict[items[i]]);
                    }
                }
            }

            subKeys = subKeyList.ToArray();
            return items.ToArray();
        }

        /// <summary>
        /// 初始化反序的字典
        /// </summary>
        /// <param name="key"></param>
        private void InitReversedDict(int key)
        {
            if (mainReversedDict == null)
            {
                mainReversedDict = new Dictionary<int, Dictionary<string, string>>();
            }

            if (!mainReversedDict.ContainsKey(key))
            {
                Dictionary<string, string> subReversedDict = new Dictionary<string, string>();

                Dictionary<string, string> subDict = mainDict[key];
                foreach (KeyValuePair<string, string> item in subDict)
                {
                    subReversedDict.Add(item.Value, item.Key);
                }

                mainReversedDict[key] = subReversedDict;
            }
        }

        /// <summary>
        /// 添加一个字典
        /// </summary>
        /// <param name="key"></param>
        /// <param name="subKey"></param>
        /// <param name="value"></param>
        public void Add(int key, string subKey, string value)
        {
            if (mainDict.ContainsKey(key))
            {
                Dictionary<string, string> subDict = mainDict[key];
                if (subDict.ContainsKey(subKey))
                {
                    throw new DictException(string.Format(Resources.SubDictKeyAlreadyExists, subKey));
                }

                Dictionary<string, string> subReversedDict = mainReversedDict[key];
                if (subReversedDict.ContainsKey(value))
                {
                    throw new DictException(string.Format(Resources.SubDictValueAlreadyExists, value));
                }

                subDict.Add(subKey, value);
                subReversedDict.Add(value, subKey);
            }
            else
            {
                Dictionary<string, string> subDict = new Dictionary<string,string>();
                subDict.Add(subKey, value);
                mainDict.Add(key, subDict);

                Dictionary<string, string> subReversedDict = new Dictionary<string, string>();
                subReversedDict.Add(value, subKey);
                mainReversedDict.Add(key, subReversedDict);
            }
        }

        /// <summary>
        /// 保存字典值到字典
        /// </summary>
        public void Save()
        {
            Save(AmsEnvironment.GetSystemPath(SystemPath.DictFile));
        }

        /// <summary>
        /// 保存字典值到字典(未实现)
        /// </summary>
        /// <param name="fileName"></param>
        public void Save(string fileName)
        {
            throw new NotImplementedException();
        }
    }
}
